// /​**​
//  * Copyright 2025 Beijing Volcano Engine Technology Co., Ltd. All Rights Reserved.
//  * SPDX-license-identifier: BSD-3-Clause
//  */

import openAPIs from '@/app/api';
import { finishPractice, getPracticeConfig, startPractice } from '@/app/fetch';
import aigcConfig from '@/config';
import { COMMAND, INTERRUPT_PRIORITY } from '@/utils/handler';
import Utils from '@/utils/utils';
import { Message } from '@arco-design/web-react';
import VERTC, {
  AudioProfileType,
  AutoPlayFailedEvent,
  DeviceInfo,
  IRTCEngine,
  LocalAudioPropertiesInfo,
  LocalStreamStats,
  MediaType,
  MirrorType,
  NetworkQuality,
  PlayerEvent,
  RemoteAudioPropertiesInfo,
  RemoteStreamStats,
  RoomProfileType,
  ScreenEncoderConfig,
  StreamIndex,
  StreamRemoveReason,
  VideoRenderMode,
  onUserJoinedEvent,
  onUserLeaveEvent,
} from '@volcengine/rtc';
import RTCAIAnsExtension from '@volcengine/rtc/extension-ainr';
import { useSelector } from 'react-redux';
import Config from '@/config';
import { RootState } from '@/store';
import { useNavigate } from "react-router-dom"
import store from '@/store';
import { updateLastMsgEndMs } from '@/store/slices/room';
import type { Msg } from '@/store/slices/room';

// 告警类型枚举
enum ALERT_TYPE {
  AI_REPLY_FAILURE = 'ai_reply_failure',        // AI回复失败
  ASR_FAILURE = 'asr_failure',                  // ASR识别失败
  TTS_FAILURE = 'tts_failure',                  // TTS合成失败
  CONVERSATION_STALLED = 'conversation_stalled', // 对话卡死
  AUDIO_SERVICE_DOWN = 'audio_service_down',     // 语音服务中断
}

export interface IEventListener {
  handleError: (e: { errorCode: any }) => void;
  handleUserJoin: (e: onUserJoinedEvent) => void;
  handleUserLeave: (e: onUserLeaveEvent) => void;
  handleTrackEnded: (e: { kind: string; isScreen: boolean }) => void;
  handleUserPublishStream: (e: { userId: string; mediaType: MediaType }) => void;
  handleUserUnpublishStream: (e: {
    userId: string;
    mediaType: MediaType;
    reason: StreamRemoveReason;
  }) => void;
  handleRemoteStreamStats: (e: RemoteStreamStats) => void;
  handleLocalStreamStats: (e: LocalStreamStats) => void;
  handleLocalAudioPropertiesReport: (e: LocalAudioPropertiesInfo[]) => void;
  handleRemoteAudioPropertiesReport: (e: RemoteAudioPropertiesInfo[]) => void;
  handleAudioDeviceStateChanged: (e: DeviceInfo) => void;
  handleAutoPlayFail: (e: AutoPlayFailedEvent) => void;
  handlePlayerEvent: (e: PlayerEvent) => void;
  handleUserStartAudioCapture: (e: { userId: string }) => void;
  handleUserStopAudioCapture: (e: { userId: string }) => void;
  handleRoomBinaryMessageReceived: (e: { userId: string; message: ArrayBuffer }) => void;
  handleNetworkQuality: (
    uplinkNetworkQuality: NetworkQuality,
    downlinkNetworkQuality: NetworkQuality
  ) => void;
}

interface EngineOptions {
  appId: string;
  uid: string;
  roomId: string;
  token: string;
}

export interface PracticeBody {
  taskId: string;
  practiceId: number;
}

export interface BasicBody {
  room_id: string;
  user_id: string;
  login_token: string | null
}

// /​**​
//  * @brief RTC Core Client
//  * @notes Refer to official website documentation to get more information about the API.
//  */
export class RTCClient {
  engine!: IRTCEngine;
  config!: EngineOptions;
  basicInfo!: BasicBody;
  practiceInfo!: PracticeBody;
  
  // 告警相关状态
  private aiReplyTimeoutTimer: NodeJS.Timeout | null = null;
  private aiReplyFailureCount = 0;
  private asrFailureCount = 0;
  private asrSuccessCount = 0;
  private ttsFailureCount = 0;
  private lastUserInputTime = 0;
  
  private _audioCaptureDevice?: string;
  private _videoCaptureDevice?: string;
  audioBotEnabled = false;
  audioBotStartTime = 0;
  chatMessage = [];
  private store: any;

  constructor() {
    this.store = store;
  }

  createEngine = async (props: EngineOptions) => {
    this.config = props;
    this.basicInfo = {
      room_id: props.roomId,
      user_id: props.uid,
      login_token: props.token,
    };
    this.practiceInfo = {
      practiceId: 0,
      taskId: ""
    }
    this.engine = VERTC.createEngine(this.config.appId);
    try {
      const AIAnsExtension = new RTCAIAnsExtension();
      await this.engine.registerExtension(AIAnsExtension);
      AIAnsExtension.enable();
    } catch (error) {
      console.warn(
        `当前环境不支持 AI 降噪, 此错误可忽略, 不影响实际使用, e: ${(error as any).message}`
      );
    }
  };

  // /​**​
  //  * 发送告警到监控系统
  //  */
  private sendAlert(type: ALERT_TYPE, message: string, details?: any) {
    console.error(`发送告警[ALERT] ${type}: ${message}`, details);
    
    // 实际告警系统调用（根据实际环境实现）
  }

  addEventListeners = ({
    handleError,
    handleUserJoin,
    handleUserLeave,
    handleTrackEnded,
    handleUserPublishStream,
    handleUserUnpublishStream,
    handleRemoteStreamStats,
    handleLocalStreamStats,
    handleLocalAudioPropertiesReport,
    handleRemoteAudioPropertiesReport,
    handleAudioDeviceStateChanged,
    handleAutoPlayFail,
    handlePlayerEvent,
    handleUserStartAudioCapture,
    handleUserStopAudioCapture,
    handleRoomBinaryMessageReceived,
    handleNetworkQuality,
  }: IEventListener) => {
    this.engine.on(VERTC.events.onError, (e) => {
      // 监控ASR错误 (假设错误码5000-5999是ASR相关)
      //@ts-ignore
      if (e.errorCode >= 5000 && e.errorCode < 6000) {
        this.asrFailureCount++;
        //@ts-ignore
        this.checkAsrFailureRate();
      }
      handleError(e);
    });
    
    this.engine.on(VERTC.events.onRoomBinaryMessageReceived, (e) => {
      try {
        // AI回复处理
        //@ts-ignore
        const msgString = Utils.tlv2String(e.message);
        //@ts-ignore
        const msgData = JSON.parse(msgString);
        
        // AI回复成功，重置计数器
        this.resetAiReplyMonitoring();
        
        // 检查AI回复异常
        if (!msgData.content || msgData.content.trim() === "") {
          this.aiReplyFailureCount++;
          if (this.aiReplyFailureCount > 2) {
            this.sendAlert(
              ALERT_TYPE.AI_REPLY_FAILURE, 
              "AI连续3次返回空回复",
              { count: this.aiReplyFailureCount, lastMessage: msgData }
            );
          }
        }
      } catch (error) {
        //@ts-ignore
        this.sendAlert(
          ALERT_TYPE.AI_REPLY_FAILURE, 
          "AI响应解析失败", 
          //@ts-ignore
          { error: error.message }
        );
      }
      
      handleRoomBinaryMessageReceived(e);
    });
    
    // TTS合成失败监控
    //@ts-ignore
    this.engine.on(VERTC.events.onPlayerEvent, (e: PlayerEvent) => {
      //@ts-ignore
      if (e.event === 'PLAYER_EVENT_AUDIO_SYNTHESIS_FAILED') {
        this.ttsFailureCount++;
        if (this.ttsFailureCount > 0) {
          this.sendAlert(
            ALERT_TYPE.TTS_FAILURE, 
            "TTS合成失败", 
            { count: this.ttsFailureCount, event: e }
          );
        }
      }
      handlePlayerEvent(e);
    });
    
    // 音频服务中断监控
    this.engine.on(VERTC.events.onUserUnpublishStream, (e) => {
      if (e.mediaType === MediaType.AUDIO && e.reason !== StreamRemoveReason.STREAM_REMOVE_REASON_OTHER) {
        this.sendAlert(
          ALERT_TYPE.AUDIO_SERVICE_DOWN, 
          "音频服务异常中断", 
          { reason: e.reason, userId: e.userId }
        );
      }
      handleUserUnpublishStream(e);
    });
    
    // 其他事件监听器的连接...
    this.engine.on(VERTC.events.onUserJoined, handleUserJoin);
    this.engine.on(VERTC.events.onUserLeave, handleUserLeave);
    this.engine.on(VERTC.events.onTrackEnded, handleTrackEnded);
    this.engine.on(VERTC.events.onUserPublishStream, handleUserPublishStream);
    this.engine.on(VERTC.events.onRemoteStreamStats, handleRemoteStreamStats);
    this.engine.on(VERTC.events.onLocalStreamStats, handleLocalStreamStats);
    this.engine.on(VERTC.events.onLocalAudioPropertiesReport, handleLocalAudioPropertiesReport);
    this.engine.on(VERTC.events.onRemoteAudioPropertiesReport, handleRemoteAudioPropertiesReport);
    this.engine.on(VERTC.events.onAudioDeviceStateChanged, handleAudioDeviceStateChanged);
    this.engine.on(VERTC.events.onAutoplayFailed, handleAutoPlayFail);
    this.engine.on(VERTC.events.onUserStartAudioCapture, handleUserStartAudioCapture);
    this.engine.on(VERTC.events.onUserStopAudioCapture, handleUserStopAudioCapture);
    this.engine.on(VERTC.events.onNetworkQuality, handleNetworkQuality);
  };

  joinRoom = (token: string | null, username: string): Promise<void> => {
    this.engine.enableAudioPropertiesReport({ interval: 1000 });
    return this.engine.joinRoom(
      token,
      `${this.config.roomId!}`,
      {
        userId: this.config.uid!,
        extraInfo: JSON.stringify({
          call_scene: 'RTC-AIGC',
          user_name: username,
          user_id: this.config.uid,
        }),
      },
      {
        isAutoPublish: true,
        isAutoSubscribeAudio: true,
        roomProfileType: RoomProfileType.chat,
      }
    );
  };

  leaveRoom = async (chatMessage: any) => {
    this.chatMessage = chatMessage;
    let result = await this.stopAudioBot();
    this.audioBotEnabled = false;
    this.engine.leaveRoom();
    VERTC.destroyEngine(this.engine);
    this._audioCaptureDevice = undefined;
    return result;
  };

  checkPermission(): Promise<{
    video: boolean;
    audio: boolean;
  }> {
    return VERTC.enableDevices({
      video: false,
      audio: true,
    });
  }

  // /​**​
  //  * @brief get the devices
  //  * @returns
  //  */
  async getDevices(props?: { video?: boolean; audio?: boolean }): Promise<{
    audioInputs: MediaDeviceInfo[];
    audioOutputs: MediaDeviceInfo[];
    videoInputs: MediaDeviceInfo[];
  }> {
    const { video = false, audio = true } = props || {};
    let audioInputs: MediaDeviceInfo[] = [];
    let audioOutputs: MediaDeviceInfo[] = [];
    let videoInputs: MediaDeviceInfo[] = [];
    const { video: hasVideoPermission, audio: hasAudioPermission } = await VERTC.enableDevices({
      video,
      audio,
    });
    if (audio) {
      const inputs = await VERTC.enumerateAudioCaptureDevices();
      const outputs = await VERTC.enumerateAudioPlaybackDevices();
      audioInputs = inputs.filter((i) => i.deviceId && i.kind === 'audioinput');
      audioOutputs = outputs.filter((i) => i.deviceId && i.kind === 'audiooutput');
      this._audioCaptureDevice = audioInputs.filter((i) => i.deviceId)?.[0]?.deviceId;
      if (hasAudioPermission) {
        if (!audioInputs?.length) {
          Message.error('无麦克风设备, 请先确认设备情况。');
        }
        if (!audioOutputs?.length) {
          Message.error('无扬声器设备, 请先确认设备情况。');
        }
      } else {
        // Message.error('暂无麦克风设备权限, 请先确认设备权限授予情况。');
      }
    }
    if (video) {
      videoInputs = await VERTC.enumerateVideoCaptureDevices();
      videoInputs = videoInputs.filter((i) => i.deviceId && i.kind === 'videoinput');
      this._videoCaptureDevice = videoInputs?.[0]?.deviceId;
      if (hasVideoPermission) {
        if (!videoInputs?.length) {
          Message.error('无摄像头设备, 请先确认设备情况。');
        }
      } else {
        Message.error('暂无摄像头设备权限, 请先确认设备权限授予情况。');
      }
    }

    return {
      audioInputs,
      audioOutputs,
      videoInputs,
    };
  }

  startVideoCapture = async (camera?: string) => {
    await this.engine.startVideoCapture(camera || this._videoCaptureDevice);
  };

  stopVideoCapture = async () => {
    this.engine.setLocalVideoMirrorType(MirrorType.MIRROR_TYPE_RENDER);
    await this.engine.stopVideoCapture();
  };

  startScreenCapture = async (enableAudio = false) => {
    await this.engine.startScreenCapture({
      enableAudio,
    });
  };

  stopScreenCapture = async () => {
    await this.engine.stopScreenCapture();
  };

  startAudioCapture = async (mic?: string) => {
    await this.engine.startAudioCapture(mic || this._audioCaptureDevice);
  };

  stopAudioCapture = async () => {
    await this.engine.stopAudioCapture();
  };

  publishStream = (mediaType: MediaType) => {
    this.engine.publishStream(mediaType);
  };

  unpublishStream = (mediaType: MediaType) => {
    this.engine.unpublishStream(mediaType);
  };

  publishScreenStream = async (mediaType: MediaType) => {
    await this.engine.publishScreen(mediaType);
  };

  unpublishScreenStream = async (mediaType: MediaType) => {
    await this.engine.unpublishScreen(mediaType);
  };

  setScreenEncoderConfig = async (description: ScreenEncoderConfig) => {
    await this.engine.setScreenEncoderConfig(description);
  };

  // /​**​
  //  * @brief 设置业务标识参数
  //  * @param businessId
  //  */
  setBusinessId = (businessId: string) => {
    this.engine.setBusinessId(businessId);
  };

  setAudioVolume = (volume: number) => {
    this.engine.setCaptureVolume(StreamIndex.STREAM_INDEX_MAIN, volume);
    this.engine.setCaptureVolume(StreamIndex.STREAM_INDEX_SCREEN, volume);
  };

  // /​**​
  //  * @brief 设置音质档位
  //  */
  setAudioProfile = (profile: AudioProfileType) => {
    this.engine.setAudioProfile(profile);
  };

  // /​**​
  //  * @brief 切换设备
  //  */
  switchDevice = (deviceType: MediaType, deviceId: string) => {
    if (deviceType === MediaType.AUDIO) {
      this._audioCaptureDevice = deviceId;
      this.engine.setAudioCaptureDevice(deviceId);
    }
    if (deviceType === MediaType.VIDEO) {
      this._videoCaptureDevice = deviceId;
      this.engine.setVideoCaptureDevice(deviceId);
    }
    if (deviceType === MediaType.AUDIO_AND_VIDEO) {
      this._audioCaptureDevice = deviceId;
      this._videoCaptureDevice = deviceId;
      this.engine.setVideoCaptureDevice(deviceId);
      this.engine.setAudioCaptureDevice(deviceId);
    }
  };

  setLocalVideoMirrorType = (type: MirrorType) => {
    return this.engine.setLocalVideoMirrorType(type);
  };

  setLocalVideoPlayer = (
    userId: string,
    renderDom?: string | HTMLElement,
    isScreenShare = false
  ) => {
    return this.engine.setLocalVideoPlayer(
      isScreenShare ? StreamIndex.STREAM_INDEX_SCREEN : StreamIndex.STREAM_INDEX_MAIN,
      {
        renderDom,
        userId,
        renderMode: VideoRenderMode.RENDER_MODE_FILL,
      }
    );
  };

  // /​**​
  //  * @brief 启用 AIGC
  //  */
  startAudioBot = async () => {
    const agentConfig = aigcConfig.aigcConfig.AgentConfig;
    const roomId = this.basicInfo.room_id;
    const userId = this.basicInfo.user_id;
    
    if (this.audioBotEnabled) {
      await this.stopAudioBot();
    }
    
    let configResponse = await getPracticeConfig()
    const options = {
      AppId: configResponse.data.AppId,
      RoomId: configResponse.data.RoomId,
      TaskId: configResponse.data.AgentConfig.UserId,
      AgentConfig: {
        ...configResponse.data.AgentConfig,
      },
      Config: configResponse.data.Config,
    };
    
    let practiceData = await startPractice()
    this.practiceInfo.practiceId = practiceData.data.practice_id;
    this.practiceInfo.taskId = configResponse.data.TaskId;
    
    // 启动音频机器人
    this.audioBotEnabled = true;
    this.audioBotStartTime = Date.now();
    Utils.setSessionInfo({ audioBotEnabled: 'enable' });
    store.dispatch({ type: 'room/setStartTime', payload: { startTime: Date.now() } });
    
    // 初始化监控
    this.resetAllMonitoring();
  };

  // /​**​
  //  * @brief 关闭 AIGC
  //  */
  stopAudioBot = async () => {
    const endTime = Date.now();
    this.store.dispatch(updateLastMsgEndMs({ endMs: endTime }));
    let startTime = this.audioBotStartTime
    const timestamp = Date.now() - startTime
    let audioBotTime = new Date(timestamp)
    const roomId = this.basicInfo.room_id;
    const state = store.getState();
    const msgHistory = state.room.msgHistory;
    
    if (msgHistory.length) {
      const lastMsg = msgHistory[msgHistory.length - 1];
      if (!lastMsg.end_ms || lastMsg.end_ms === 0) {
        store.dispatch({
          type: 'room/updateLastMsgEndMs',
          payload: { end_ms: Date.now() - state.room.startTime }
        });
      }
    }
    
    if (this.audioBotEnabled || sessionStorage.getItem('audioBotEnabled')) {
      let training_id = localStorage?.getItem('training_id')
      let chatMessage = this.store.getState().room.msgHistory.map((m: Msg) => ({
        role: m.user === Config.BotName + training_id ? 'system' : 'user',
        content: m.value,
        start_ms: m.start_ms ?? 0,
        end_ms: m.end_ms ?? 0,
      }));
      
      let res = await finishPractice(
        this.practiceInfo.practiceId,
        aigcConfig.BaseConfig.AppId,
        roomId,
        this.practiceInfo.taskId,
        audioBotTime.getSeconds(),
        chatMessage
      )
      
      // 停止所有监控计时器
      this.resetAiReplyMonitoring();
      
      this.audioBotStartTime = 0;
      sessionStorage.removeItem('audioBotEnabled');
    }
    
    this.audioBotEnabled = false;
    return { success: true };
  };

  // /​**​
  //  * @brief 命令 AIGC
  //  */
  commandAudioBot = (command: COMMAND, interruptMode = INTERRUPT_PRIORITY.NONE, message = '') => {
    if (this.audioBotEnabled) {
      // 记录用户提问时间
      this.lastUserInputTime = Date.now();
      
      // 启动回复超时监控
      this.startAiReplyTimeout();
      
      this.engine.sendUserBinaryMessage(
        aigcConfig.BotName,
        Utils.string2tlv(
          JSON.stringify({
            Command: command,
            InterruptMode: interruptMode,
            Message: message,
          }),
          'ctrl'
        )
      );
      return;
    }
    console.warn('Interrupt failed, bot not enabled.');
  };

  // /​**​
  //  * 启动AI回复超时监控（30秒）
  //  */
  private startAiReplyTimeout() {
    this.resetAiReplyMonitoring();
    
    this.aiReplyTimeoutTimer = setTimeout(() => {
      this.sendAlert(
        ALERT_TYPE.CONVERSATION_STALLED, 
        "用户等待超过30秒无响应",
        {
          lastUserInputTime: this.lastUserInputTime,
          currentTime: Date.now(),
          elapsed: Date.now() - this.lastUserInputTime
        }
      );
      
      // 重置状态
      this.lastUserInputTime = 0;
    }, 30000);
  }

  // /​**​
  //  * 重置AI回复监控状态
  //  */
  private resetAiReplyMonitoring() {
    if (this.aiReplyTimeoutTimer) {
      clearTimeout(this.aiReplyTimeoutTimer);
      this.aiReplyTimeoutTimer = null;
    }
    this.aiReplyFailureCount = 0;
    this.lastUserInputTime = 0;
  }

  // /​**​
  //  * 重置所有监控状态
  //  */
  private resetAllMonitoring() {
    this.resetAiReplyMonitoring();
    this.asrSuccessCount = 0;
    this.asrFailureCount = 0;
    this.ttsFailureCount = 0;
  }

  // /​**​
  //  * 检查ASR失败率是否超过阈值
  //  */
  private checkAsrFailureRate() {
    const totalRequests = this.asrSuccessCount + this.asrFailureCount;
    if (totalRequests >= 20) { // 有足够样本时才统计
      const failureRate = this.asrFailureCount / totalRequests;
      
      if (failureRate > 0.1) { // 超过10%
        this.sendAlert(
          ALERT_TYPE.ASR_FAILURE, 
          `ASR识别失败率超过阈值 (${(failureRate*100).toFixed(1)}%)`,
          {
            failureCount: this.asrFailureCount,
            successCount: this.asrSuccessCount,
            failureRate
          }
        );
      }
    }
  }

  // /​**​
  //  * @brief 更新 AIGC 配置
  //  */
  updateAudioBot = async () => {
    if (this.audioBotEnabled) {
      await this.stopAudioBot();
      await this.startAudioBot();
    } else {
      await this.startAudioBot();
    }
  };

  // /​**​
  //  * @brief 获取当前 AI 是否启用
  //  */
  getAudioBotEnabled = () => {
    return this.audioBotEnabled;
  };
  
  getPracticeId = () => {
    return this.practiceInfo.practiceId;
  };
  
  // ASR成功时调用（由外部组件实现）
  asrSuccess = () => {
    this.asrSuccessCount++;
    this.checkAsrFailureRate();
  };
}

export default new RTCClient();